package com.example.redis.Controller;

import com.example.redis.domain.ResultVO;
import com.example.redis.domain.UserDO;
import com.example.redis.domain.UserDTO;
import com.example.redis.service.UserService;
import com.example.redis.util.RedisUtils;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import support.limit.annotation.Limit;
import support.limit.util.IdentifierThreadLocal;

import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * MyController
 *
 * @Description MyController
 * @Author guoyb
 * @Date 2021/7/14 10:51
 */
@RestController
@RequestMapping("/test")
@Slf4j
public class MyController {

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private UserService userService;


    @GetMapping("/test")
    @ApiOperation("序列化测试")
    public String test() throws IOException {

        UserDTO userDTO = new UserDTO("zzz", 12);

        redisUtils.saveString("zhuzhe", "zhuzhe123");

        redisUtils.saveBean("aaa", userDTO);

        String zhuzhe = redisUtils.getString("zhuzhe");

        UserDTO aaa = redisUtils.getBean("aaa", UserDTO.class);

        System.out.println(aaa);

        return zhuzhe;
    }

    @GetMapping("/num")
    @ApiOperation("增减测试")
    public String num() throws IOException {

        String key = "num";
        redisUtils.saveLong(key, 1L);

        redisUtils.getStringRedisTemplate().opsForValue().increment(key, 10L);

        String string = redisUtils.getString(key);

        return string;
    }


    @GetMapping("/def")
    @ApiOperation("接口里默认方法")
    public String def() {
        return userService.getName(1L);
    }


    //{
    // 	"age": 0,
    // 	"id": 0,
    // 	"money": 8,
    // 	"userName": "1"
    // }
    @PostMapping("/lockTest")
    @ApiOperation("分布式锁")
    public ResultVO lockTest(@Validated @RequestBody UserDTO dto) {
        userService.lockTest(dto);
        return ResultVO.ok();
    }


    @PostMapping("/limitTest")
    @ApiOperation("限流-Limit")
    @Limit(identifier = "limitTest", key = "test", limtNum = 1, seconds = 1)
    public String limitTest(@RequestParam Long id) {
        log.info("限流-----打印日志------{}", id);
        // IdentifierThreadLocal.set( identifier );
        return userService.getName(id);
    }

    @PostMapping("/limitTest2")
    @ApiOperation("限流2-Lock4j")
    public ResultVO limitTest2(@Validated @RequestBody UserDTO dto) {
        userService.limitTest(dto);
        return ResultVO.ok();
    }


    @SneakyThrows
    @GetMapping("/caffeineTest")
    @ApiOperation("caffeineTest")
    public void caffeineTest(@RequestParam Integer id) {
        // 创建一个缓存实例
        Cache<String, String> cache = Caffeine.newBuilder()
                // 初始容量
                .initialCapacity(5)
                // 最大缓存数，超出淘汰
                .maximumSize(10)
                // 设置缓存写入间隔多久过期
                .expireAfterWrite(3, TimeUnit.SECONDS)
                // 设置缓存最后访问后间隔多久淘汰，实际很少用到
                //.expireAfterAccess(3, TimeUnit.SECONDS)
                .build();

        // 写入缓存数据
        cache.put("userName", "张三");

        // 读取缓存数据
        String value1 = cache.get("userName", (key) -> {
            // 如果key不存在，会执行回调方法
            return "key已过期";
        });
        System.out.println("第一次查询结果：" + value1);

        // 停顿4秒
        Thread.sleep(4000);

        // 读取缓存数据
        String value2 = cache.get("userName", (key) -> {
            // 如果key不存在，会执行回调方法
            return "key已过期";
        });
        System.out.println("第二次查询结果：" + value2);
    }
}
